package simulacao;

import java.util.ArrayList;

public class TabelaPayoffs {

	private ArrayList<double[][][]> tabelas;
	private double[][][] tabela;
	private static TabelaPayoffs instance;
	
	private TabelaPayoffs(){
		tabelas = new ArrayList<double[][][]>();
		inicializarTabelasPadrao();
	}
	
	public void selecionarTabela(int index){
		tabela = tabelas.get(index);
	}
	
	/**
	 * Retorna o payoff do jogador cuja jogada no turno é passada como primeiro parâmetro.
	 * @param estrategiaJogador1 a jogada do jogador 1
	 * @param estrategiaJogador2 a jogada do jogador 2
	 * @param jogador	o jogador do qual se deseja obter o payoff
	 * @return o payoff obtido pelo jogador no turno
	 */
	public double getPayoff(int estrategiaJogador1, int estrategiaJogador2, int jogador){
		return tabela[estrategiaJogador1][estrategiaJogador2][jogador];
	}
	
	public double getPayoff(int index, int estrategiaJogador1, int estrategiaJogador2, int jogador){
			return tabelas.get(index)[estrategiaJogador1][estrategiaJogador2][jogador];
	}
	
	public static TabelaPayoffs getInstance(){
		if (instance == null) instance = new TabelaPayoffs();
		return instance;
	}
	
	public double[][][] getTabela(int index){
		return tabelas.get(index);
	}
	
	public void adicionarTabela(double[][][] tabela){
		tabelas.add(0, tabela);
		selecionarTabela(0);
	}
	
	public void adicionarTabela(String tabelaStr){
		int numJogadores = 2, numJogadas1 = 2, numJogadas2 = 2;
		double[][][] novaTabela = new double[numJogadas1][numJogadas2][numJogadores];
		String[] valores = tabelaStr.replaceAll("\\[","").replaceAll("\\]","/").split("/");
		for (int i = 0; i < numJogadas1; i++)
			for (int j = 0; j < numJogadas2; j++) 
				for (int k = 0; k < numJogadores; k++) 
					novaTabela[i][j][k] = Double.parseDouble(valores[numJogadas2*numJogadas1*i+numJogadas1*j+k]);
		adicionarTabela(novaTabela);
	}
	
	public void inicializarTabelasPadrao(){

		double[][][][] tabelasPadrao = new double[6][2][2][2];
		//Dilema dos prisioneiros tabela simétrica
		tabelasPadrao[0][1][1][1] = 4;
		tabelasPadrao[0][1][1][0] = 4;
		tabelasPadrao[0][1][0][1] = 3;
		tabelasPadrao[0][1][0][0] = 6;
		tabelasPadrao[0][0][1][1] = 6;
		tabelasPadrao[0][0][1][0] = 3;
		tabelasPadrao[0][0][0][1] = 5;
		tabelasPadrao[0][0][0][0] = 5;
		tabelas.add(tabelasPadrao[0]);
		
		//Tabela para adversário do tipo 1
		tabelasPadrao[1][1][1][1] = 4;
		tabelasPadrao[1][1][1][0] = 4;
		tabelasPadrao[1][1][0][1] = 3;
		tabelasPadrao[1][1][0][0] = 6;
		tabelasPadrao[1][0][1][1] = 4;
		tabelasPadrao[1][0][1][0] = 3;
		tabelasPadrao[1][0][0][1] = 5;
		tabelasPadrao[1][0][0][0] = 5;
		tabelas.add(tabelasPadrao[1]);

		//Tabela para adversário do tipo 2
		tabelasPadrao[2][1][1][1] = 4;
		tabelasPadrao[2][1][1][0] = 0;
		tabelasPadrao[2][1][0][1] = 3;
		tabelasPadrao[2][1][0][0] = 2;
		tabelasPadrao[2][0][1][1] = 4;
		tabelasPadrao[2][0][1][0] = 3;
		tabelasPadrao[2][0][0][1] = 5;
		tabelasPadrao[2][0][0][0] = 5;
		tabelas.add(tabelasPadrao[2]);
		
		//Batalha dos sexos
		tabelasPadrao[3][1][1][1] = 2;
		tabelasPadrao[3][1][1][0] = 1;
		tabelasPadrao[3][1][0][1] = 0;
		tabelasPadrao[3][1][0][0] = 0;
		tabelasPadrao[3][0][1][1] = 0;
		tabelasPadrao[3][0][1][0] = 0;
		tabelasPadrao[3][0][0][1] = 1;
		tabelasPadrao[3][0][0][0] = 2;
		tabelas.add(tabelasPadrao[3]);
		
		//Dilema dos prisioneiros com valores negativos
		tabelasPadrao[4][1][1][1] = -1;
		tabelasPadrao[4][1][1][0] = -1;
		tabelasPadrao[4][1][0][1] = -4;
		tabelasPadrao[4][1][0][0] = 3;
		tabelasPadrao[4][0][1][1] = 3;
		tabelasPadrao[4][0][1][0] = -4;
		tabelasPadrao[4][0][0][1] = 1;
		tabelasPadrao[4][0][0][0] = 1;
		tabelas.add(tabelasPadrao[4]);
		
		//Batalha dos sexos com valores negativos
		tabelasPadrao[5][1][1][1] = 3;
		tabelasPadrao[5][1][1][0] = 1;
		tabelasPadrao[5][1][0][1] = -2;
		tabelasPadrao[5][1][0][0] = -2;
		tabelasPadrao[5][0][1][1] = 0;
		tabelasPadrao[5][0][1][0] = 0;
		tabelasPadrao[5][0][0][1] = 1;
		tabelasPadrao[5][0][0][0] = 3;
		tabelas.add(tabelasPadrao[5]);
	}
}
